const createError = require("http-errors");
const express = require("express");
const path = require("path");
const cookieParser = require("cookie-parser");
const logger = require("morgan");
const { expressjwt } = require("express-jwt");
const md5 = require("md5");
const session = require("express-session");

const {
  ForbiddenError,
  ServiceError,
  UnknownError,
  NotFoundError,
  ValidationError,
} = require("./utils/error");

require("dotenv").config();
require("express-async-errors");
require("./dao/db");

const adminRouter = require("./routes/admin");
const captchaRouter = require("./routes/captcha");
const bannerRouter = require("./routes/banner");
const blogTypeRouter = require("./routes/blogType");

const app = express();

app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, "public")));

app.use(
  expressjwt({
    secret: md5(process.env.JWT_SECRET),
    algorithms: ["HS256"],
  }).unless({
    path: [
      /^\/static\/.*/,
      /^\/papi\/.*/,
      { url: "/api/admin/login", methods: ["POST"] },
      { url: "/api/banner/query/findAll", methods: ["GET"] },
      { url: "/api/blogType/query/findAll", methods: ["GET"] },
    ],
  })
);

app.use(
  session({
    secret: process.env.SESSION_SECRET,
    resave: true,
    saveUninitialized: true,
  })
);

app.use("/api/admin", adminRouter);
app.use("/api/banner", bannerRouter);
app.use("/api/blogType", blogTypeRouter);
app.use("/papi/captcha", captchaRouter);

// catch 404 and forward to error handler
app.use(function (req, res, next) {
  // console.log("404");
  next(createError(404));
});

// error handler
app.use(function (err, req, res, next) {+
  console.log("err", err, err.name);
  if (err.name === "NotFoundError") {
    res.send(new NotFoundError().toResponseJSON());
  } else if (err.name === "UnauthorizedError") {
    // 说明是 token 验证错误，接下来我们来抛出我们自定义的错误
    res.send(new ForbiddenError("未登录，或者登录已经过期").toResponseJSON());
  } else if (err instanceof ServiceError) {
    res.send(err.toResponseJSON());
  } else if (
    ["SequelizeUniqueConstraintError", "SequelizeValidationError"].includes(
      err.name
    )
  ) {
    res.send(new ValidationError(err.errors[0].message).toResponseJSON());
  } else {
    res.send(new UnknownError().toResponseJSON());
  }
});

module.exports = app;
